<?php

namespace App\Services\WebSocket;


use function GuzzleHttp\json_encode;

class WebSocketService
{

    /*------------------------------------------------------ */
//-- 语音听写（流式版）WebAPI PHP示例
//-- 需要安装websocket，我用的是下面链接提供的
//-- https://github.com/Textalk/websocket-php
    /*------------------------------------------------------ */

    /*------------------------------------------------------ */
//-- 拼接签名
//-- 请查看语音听写-流式版-webapi-文档里的鉴权方法
//-- @param $api_key
//-- @param $api_secret
//-- @param $time
//-- @return string
    /*------------------------------------------------------ */
    public function sign($api_key, $api_secret, $time)
    {
        $signature_origin = 'host: iat-api.xfyun.cn' . "\n";
        $signature_origin .= 'date: ' . $time . "\n";
        $signature_origin .= 'GET /v2/iat HTTP/1.1';
        $signature_sha = hash_hmac('sha256', $signature_origin, $api_secret, true);
        $signature_sha = base64_encode($signature_sha);
        $authorization_origin = 'api_key="' . $api_key . '", algorithm="hmac-sha256", ';
        $authorization_origin .= 'headers="host date request-line", signature="' . $signature_sha . '"';
        $authorization = base64_encode($authorization_origin);
        return $authorization;
    }

    /*------------------------------------------------------ */
//-- 生成请求Url
//-- 请查看语音听写-流式版-webapi-文档里的鉴权方法
//-- @param $api_key
//-- @param $api_secret
//-- @return string
    /*------------------------------------------------------ */
    public function createurl($api_key, $api_secret)
    {
        $url = 'ws://iat-api.xfyun.cn/v2/iat';
        $time = gmdate('D, d M Y H:i:s', time() + 8 * 3600) . ' GMT';
        $authorization = $this->sign($api_key, $api_secret, $time);
        $url .= '?' . 'authorization=' . $authorization . '&date=' . urlencode($time) . '&host=iat-api.xfyun.cn';
        return $url;
    }
    /*------------------------------------------------------ */
//-- 发送的数据(第一帧)
//-- 请查看语音听写-流式版-webapi-文档里的请求参数
//-- @param $app_id
//-- @param $status
//-- @param $audio
//-- @return array
    /*------------------------------------------------------ */
    public function createfirstframedata($app_id, $status, $audio)
    {
        return [
            'common' => [
                'app_id' => $app_id,//平台申请的APPID信息
            ],
            'business' => [
                'language' => 'zh_cn',//语种
                'domain' => 'iat',//应用领域，iat：日常用语
                'accent' => 'mandarin',//方言，mandarin：中文普通话、其他语种
            ],
            'data' => [
                'status' => $status,//音频的状态
                'format' => 'audio/L16;rate=16000',//音频的采样率
                'encoding' => "speex-wb",//音频数据格式，这里使用speex压缩后的音频（16k）
                'audio' => base64_encode($audio),//音频内容，采用base64编码
            ],
        ];
    }
    /*------------------------------------------------------ */
//-- 发送的数据(非第一帧)
//-- 请查看语音听写-流式版-webapi-文档里的请求参数
//-- common和business参数只需要在握手成功后的第一帧请求时带上
//-- @param $status
//-- @param $audio
//-- @return array
    /*------------------------------------------------------ */
    public function createotherframesdata($status, $audio)
    {
        return [
            'data' => [
                'status' => $status,//音频的状态
                'format' => 'audio/L16;rate=16000',//音频的采样率
                'encoding' => "speex-wb",//音频数据格式，这里使用speex压缩后的音频（16k）
                'audio' => base64_encode($audio),//音频内容，采用base64编码
            ],
        ];
    }
    /*------------------------------------------------------ */
//-- 测试本地文件程序
    /*------------------------------------------------------ */
    public function make()
    {
        $app_id = '08352b85'; //apiId
        $api_key = '0310c8ef2d633146823ac4deaf08ea6a'; //apiKey
        $api_secret = 'N2VjNjQyYWY3N2ZlYTlkYTc1NmIwOTk0'; //apiSecret
        $file = public_path() . "/files/iat_speex-wb_16k.speex"; //可以在讯飞提供的音频样例中下载
        $url = $this->createurl($api_key, $api_secret);
        $client = new \WebSocket\Client($url);
        try {
            //请查看语音听写-流式版-webapi-文档里的接口数据传输与接收
            //本示例用了讯飞定制speex格式，每次发送音频间隔40ms，压缩等级为7，每次发送61B的整数倍
            $frameSize = 61;//每一帧音频大小的整数倍
            $intervel = 40000;//每次发送音频间隔40ms，单位微秒，1毫秒=1000微秒
            $status = 0;// 音频的状态，0 :第一帧音频，1 :中间的音频，2 :最后一帧音频，最后一帧必须要发送
            $f = fopen($file, "rb");
            if ($f === false)
                die();
            while (!feof($f)) {
                usleep($intervel);
                clearstatcache(false, $file);
                $contents = fread($f, $frameSize);
                if (!$contents) {
                    $status = 2;
                }

                if ($status == 0) {
                    $message = $this->createfirstframedata($app_id, 0, $contents);
                    $client->send(json_encode($message, true));
                    $status = 1;
                } elseif ($status == 1) {
                    $message = $this->createotherframesdata(1, $contents);
                    $client->send(json_encode($message, true));
                } elseif ($status == 2) {
                    $message = $this->createotherframesdata(2, $contents);
                    $client->send(json_encode($message, true));
                    break;
                }
            }
            fclose($f);

            $data = $client->receive();
            //转换为JSON格式
            return json_decode($data, true);
        } catch
        (Exception $e) {
            $re = $e->getMessage();
            echo "Error: $re \n";
        } finally {
            $client->close();
        }

    }


    public function send($file)
    {

        $app_id = '08352b85'; //apiId
        $api_key = '0310c8ef2d633146823ac4deaf08ea6a'; //apiKey
        $api_secret = 'N2VjNjQyYWY3N2ZlYTlkYTc1NmIwOTk0'; //apiSecret
//        $file = public_path() . "/files/iat_speex-wb_16k.speex"; //可以在讯飞提供的音频样例中下载

//        $file为前台上传的音频流文件



        $url = $this->createurl($api_key, $api_secret);
        $client = new \WebSocket\Client($url);
        try {
            //请查看语音听写-流式版-webapi-文档里的接口数据传输与接收
            //本示例用了讯飞定制speex格式，每次发送音频间隔40ms，压缩等级为7，每次发送61B的整数倍
            $frameSize = 61;//每一帧音频大小的整数倍
            $intervel = 40000;//每次发送音频间隔40ms，单位微秒，1毫秒=1000微秒
            $status = 0;// 音频的状态，0 :第一帧音频，1 :中间的音频，2 :最后一帧音频，最后一帧必须要发送
            $f = fopen($file, "rb");
            if ($f === false)
                die();
            while (!feof($f)) {
                usleep($intervel);
                clearstatcache(false, $file);
                $contents = fread($f, $frameSize);
                if (!$contents) {
                    $status = 2;
                }

                if ($status == 0) {
                    $message = $this->createfirstframedata($app_id, 0, $contents);
                    $client->send(json_encode($message, true));
                    $status = 1;
                } elseif ($status == 1) {
                    $message = $this->createotherframesdata(1, $contents);
                    $client->send(json_encode($message, true));
                } elseif ($status == 2) {
                    $message = $this->createotherframesdata(2, $contents);
                    $client->send(json_encode($message, true));
                    break;
                }
            }
            fclose($f);

            $data = $client->receive();
            //转换为JSON格式
            return json_decode($data, true);
        } catch
        (Exception $e) {
            $re = $e->getMessage();
            echo "Error: $re \n";
        } finally {
            $client->close();
        }

    }
}